<?php
require APP_PATH.'models'.DS.'jadwal_kerja'.DS.'JadwalKerjaBL.php';
require APP_PATH.'models'.DS.'jam_kerja'.DS.'JamKerjaBL.php';

class AbsensiReportController extends AppController {
   
   public $name = 'AbsensiReport';
   public $uses = array();
   
   public function reportDailyPage($startdate = '2012-04-01',$enddate = '2012-04-24') {
      App::import('Lib','MixedUtils');
      App::import('Lib','Absence');

      $mixedUtils = new MixedUtils();
      
      $dataReports = array();
      $datesRange = $this->__listDateFromDateRange($startdate, $enddate);
       
      // --- Dapatkan semua karyawan
      $this->paginate = array(
          'conditions' => array('Karyawan.id' => 1)
      );
      
      $karyawanList = $this->paginate(ClassRegistry::init('Karyawan'));

      // --- Loop through karyawan
      $usrIndex = 0;
      foreach ($karyawanList as $karyawan) {

         // --- Dapatkan jadwal kerja dari current karyawan pada putaran foreach()
         $jadwalKerjaBL = new JadwalKerjaBL();
         
         $jadwalKerjaData = $jadwalKerjaBL->jadwalKerjaFind('first', array(
             'conditions' => array('JadwalKerja.id' => $karyawan['KaryawanJadwalKerja']['jadwal_kerja_id'])
             )
         );

         // Collections of report's variables
         $notpresent = 0;
         $time_of_late = 0;
         $time_of_leave_early = 0;
         $time_of_overtime = 0;
            
         // -- Loop through dates range
         $dateIndex = 0;
         $associativeIndex = 'reports';
         
         foreach ($datesRange as $date) {
            $go_ahead = true;

            $dataReports[$usrIndex]["employee_username"] = $karyawan['Karyawan']['nama'];
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absent"] = 0;
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["tanggal"] = $date;
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja"] = "---";
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja_masuk"] = "---";
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja_pulang"] = "---";
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absen_masuk"] = "---";
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absen_pulang"] = "---";
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["terlambat"] = 0;
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["pulang_awal"] = 0;
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["lembur"] = 0;
         
            // --- Dapatkan urutan hari. Digunakan untuk select 
            // --- field hari_$dayOrder di model JadwalKerja
            $dayOrder = $this->__getDayOrder(
                     $date,
                     $jadwalKerjaData['JadwalKerja']['awal_masa_berlaku'],
                     $jadwalKerjaData['JadwalKerja']['perputaran']
                );
            
            // --- Lalu, dapatkan detail jam kerja melalui field 
            // --- hari_$dayOrder yg ada di model JadwalKerja
            $theDay = 'hari_'.$dayOrder;
            $dataReports[$usrIndex][$associativeIndex][$dateIndex]["hari_ke"] = $dayOrder;
           
            // --- Jika sang karyawan pada current tanggal memang ADA jadwal
            if ($jadwalKerjaData['JadwalKerja'][$theDay] != 0) { // START IF UNTUK JIKA ADA JADWAL
               
               // Dapatkan jam kerja
               $jamKerjaBL = new JamKerjaBL();
               $jamKerjaList = $jamKerjaBL->jamKerjaFind('first',array(
                     'conditions' => array('JamKerja.id' => $jadwalKerjaData['JadwalKerja'][$theDay])
                  )
               );
                  
               // --- Mencari Chectime IN dan OUT
               if (($jamKerjaList['JamKerja']['cyc_in'] == 2) || ($jamKerjaList['JamKerja']['cyc_out'] == 2)) { // // START IF JIKA CYCLE IN or OUT == 2
                  
                  $nextDate = date("Y-m-d",strtotime(date("Y-m-d",strtotime($date))."+1 day"));
                  
                  // Modifikasi Jam Kerja
                  $jamKerjaListModified = $this->__addDateToEachTime($jamKerjaList,$date,$nextDate);
                  $jamKerjaList = null;

                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja"] = $jamKerjaListModified['JamKerja']['nama'];
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja_masuk"] = substr($jamKerjaListModified['JamKerja']['waktu_masuk'], stripos($jamKerjaListModified['JamKerja']['waktu_masuk'], ' '), strlen($jamKerjaListModified['JamKerja']['waktu_masuk']));
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja_pulang"] = substr($jamKerjaListModified['JamKerja']['waktu_keluar'], stripos($jamKerjaListModified['JamKerja']['waktu_keluar'], ' '), strlen($jamKerjaListModified['JamKerja']['waktu_keluar']));
                  
                  $checktimeList = ClassRegistry::init('Checktime')->find('all',array(
                      'conditions' => array(
                          'DATE(Checktime.checktime) BETWEEN ? AND ?' => array($date,$nextDate),
                          'Checktime.user_id' => $karyawan['Karyawan']['id']
                        ),
                      
                      'order' => array('Checktime.checktime')
                     )
                      
                  );
                  
                  $dateTimeArray = array(
                      'absenceIn' => $jamKerjaListModified['JamKerja']['waktu_masuk'],
                      'absenceOut' => $jamKerjaListModified['JamKerja']['waktu_keluar'],
                      'absenceInBegin' => $jamKerjaListModified['JamKerja']['batas_awal_masuk'],
                      'absenceInEnd' => $jamKerjaListModified['JamKerja']['batas_akhir_masuk'],
                      'absenceOutBegin' => $jamKerjaListModified['JamKerja']['batas_awal_keluar'],
                      'absenceOutEnd' => $jamKerjaListModified['JamKerja']['batas_akhir_keluar'],
                      'lateTimeTolerance' => $jamKerjaListModified['JamKerja']['waktu_toleransi_telat'],
                      'leaveTimeTolerance' => $jamKerjaListModified['JamKerja']['waktu_toleransi_keluar_awal'],
                      'overTimeBegin' => $jamKerjaListModified['JamKerja']['waktu_awal_lembur']
                  );
                  
                  $absence = new Absence($dateTimeArray);
                  
                  // START hitung absen //
                  $in = array();
                  $out = array();
                  
                  // Cari mana yg termasuk IN dan mana yg termasuk OUT
                  foreach ($checktimeList as $itemTime) {
                     if ($absence->isAbsenceIn($itemTime['Checktime']['checktime'])) {
                        array_push($in, strtotime($itemTime['Checktime']['checktime']));
                        
                     }
                     
                     if ($absence->isAbsenceOut($itemTime['Checktime']['checktime'])) {
                        array_push($out, strtotime($itemTime['Checktime']['checktime']));
                     }
                  }
                  
                  $countIN = count($in);
                  $countOUT = count($out);
                  $minTime = null;
                  $maxTime = null;
                  
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absen_masuk"] = ($countIN == 0) ? '---' : date('H:i:s', $minTime = min($in));
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absen_pulang"] = ($countOUT == 0) ? '---' : date('H:i:s', $maxTime = max($out));
                  
                  // --- Check apakah alpha?
                  if ($countIN == 0 && $countOUT == 0) {
                     $notpresent = 1;
                     $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absent"] = $notpresent;
                     
                  }
                  
                  // Check apakah telat karena tidak ada absen IN, tetapi ada absen OUT
                  if (($countIN == 0) && ($countOUT != 0)) {
                     $time_of_late = $time_of_late + $absence->calculateTotalHoursOfLate('NO_IN');
                     
                     $mixedUtils = new MixedUtils();
                     $secToTime = $mixedUtils->sec2Time($time_of_late);
                                        
                     $dataReports[$usrIndex][$associativeIndex][$dateIndex]["terlambat"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                  }
                  
                  // Check apakah pulang awal dengan kondisi ada absen IN tetapi tidak ada absen OUT
                  if (($countIN != 0) && ($countOUT == 0)) {
                     $time_of_leave_early = $time_of_leave_early + $absence->calculateTotalHoursOfLeaveEarly('NO_OUT');
                     
                     $mixedUtils = new MixedUtils();
                     $secToTime = $mixedUtils->sec2Time($time_of_leave_early);
                                        
                     $dataReports[$usrIndex][$associativeIndex][$dateIndex]["pulang_awal"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                  }

                  // Check keterlambatan dan pulang awal dengan kondisi ada absen IN dan ada absen OUT
                  if (($countIN != 0) && ($countOUT != 0)) {
                     
                     // Terlambat
                     if ($absence->isComeLate(date('Y-m-d H:i:s',$minTime))) {
                        $time_of_late = $time_of_late + $absence->calculateTotalHoursOfLate('COMPLETE',date('Y-m-d H:i:s',$minTime));
                        
                        $mixedUtils = new MixedUtils();
                        $secToTime = $mixedUtils->sec2Time($time_of_late);
                        
                        $dataReports[$usrIndex][$associativeIndex][$dateIndex]["terlambat"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                     }
                     
                     // Pulang awal
                     if ($absence->isLeaveEarly(date('Y-m-d H:i:s',$maxTime))) {
                        $time_of_leave_early = $time_of_leave_early + $absence->calculateTotalHoursOfLeaveEarly('COMPLETE',date('Y-m-d H:i:s',$maxTime));
                     
                        $mixedUtils = new MixedUtils();
                        $secToTime = $mixedUtils->sec2Time($time_of_leave_early);
                        
                        $dataReports[$usrIndex][$associativeIndex][$dateIndex]["pulang_awal"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                     }
                     
                     // Check apakah overtime
                     if ($absence->isOverTime(date('Y-m-d H:i:s',$maxTime))) {

                        $timediff_overtime = $maxTime - strtotime($absence->getOverTimeBegin());
                        $time_of_overtime = $time_of_overtime+$timediff_overtime;
                        $secToTime = $mixedUtils->sec2Time($time_of_overtime);

                        $dataReports[$usrIndex][$associativeIndex][$dateIndex]["lembur"] = $secToTime["hours"].":".$secToTime["minutes"].":".$secToTime["seconds"];
                     }
                     
                  }

                  // END hitung absen //
                   
               } else { // START IF JIKA CYCLE IN or OUT != 2
                  
                  // Modifikasi Jam Kerja
                  $jamKerjaListModified = $this->__addDateToEachTime($jamKerjaList,$date);
                  $jamKerjaList = null;

                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja"] = $jamKerjaListModified['JamKerja']['nama'];
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja_masuk"] = substr($jamKerjaListModified['JamKerja']['waktu_masuk'], stripos($jamKerjaListModified['JamKerja']['waktu_masuk'], ' '), strlen($jamKerjaListModified['JamKerja']['waktu_masuk']));
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["jam_kerja_pulang"] = substr($jamKerjaListModified['JamKerja']['waktu_keluar'], stripos($jamKerjaListModified['JamKerja']['waktu_keluar'], ' '), strlen($jamKerjaListModified['JamKerja']['waktu_keluar']));
                  
                  $checktimeList = ClassRegistry::init('Checktime')->find('all',array(
                      'conditions' => array(
                          'DATE(Checktime.checktime)' => $date,
                          'Checktime.user_id' => $karyawan['Karyawan']['id']
                        ),
                      
                      'order' => array('Checktime.checktime')
                     )
                      
                  );
                  
                  $dateTimeArray = array(
                      'absenceIn' => $jamKerjaListModified['JamKerja']['waktu_masuk'],
                      'absenceOut' => $jamKerjaListModified['JamKerja']['waktu_keluar'],
                      'absenceInBegin' => $jamKerjaListModified['JamKerja']['batas_awal_masuk'],
                      'absenceInEnd' => $jamKerjaListModified['JamKerja']['batas_akhir_masuk'],
                      'absenceOutBegin' => $jamKerjaListModified['JamKerja']['batas_awal_keluar'],
                      'absenceOutEnd' => $jamKerjaListModified['JamKerja']['batas_akhir_keluar'],
                      'lateTimeTolerance' => $jamKerjaListModified['JamKerja']['waktu_toleransi_telat'],
                      'leaveTimeTolerance' => $jamKerjaListModified['JamKerja']['waktu_toleransi_keluar_awal'],
                      'overTimeBegin' => $jamKerjaListModified['JamKerja']['waktu_awal_lembur']
                  );
                  
                  $absence = new Absence($dateTimeArray);
                  
                  // START hitung absen
                  $in = array();
                  $out = array();
                  
                  foreach ($checktimeList as $itemTime) {
                     if ($absence->isAbsenceIn($itemTime['Checktime']['checktime'])) {
                        array_push($in, strtotime($itemTime['Checktime']['checktime']));
                     }
                     
                     if ($absence->isAbsenceOut($itemTime['Checktime']['checktime'])) {
                        array_push($out, strtotime($itemTime['Checktime']['checktime']));
                     }
                  }
                  
                  $countIN = count($in);
                  $countOUT = count($out);
                  $minTime = null;
                  $maxTime = null;
                  
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absen_masuk"] = ($countIN == 0) ? '---' : date('H:i:s', $minTime = min($in));
                  $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absen_pulang"] = ($countOUT == 0) ? '---' : date('H:i:s', $maxTime = max($out));
                  
                  // --- Check apakah alpha?
                  if ($countIN == 0 && $countOUT == 0) {
                     $notpresent = 1;
                     $dataReports[$usrIndex][$associativeIndex][$dateIndex]["absent"] = $notpresent;
                  }
                  
                  // --- Check apakah telat karena tidak ada absen IN , tapi ada absen OUT
                  if (($countIN == 0) && ($countOUT != 0)) {
                     $time_of_late = $time_of_late + $absence->calculateTotalHoursOfLate('NO_IN');
                     
                     $mixedUtils = new MixedUtils();
                     $secToTime = $mixedUtils->sec2Time($time_of_late);
                     
                     $dataReports[$usrIndex][$associativeIndex][$dateIndex]["terlambat"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                  }
                  
                  // Check apakah pulang awal dengan kondisi ada absen IN tetapi tidak ada absen OUT
                  if (($countIN != 0) && ($countOUT == 0)) {
                     $time_of_leave_early = $time_of_leave_early + $absence->calculateTotalHoursOfLeaveEarly('NO_OUT');
                     
                     $mixedUtils = new MixedUtils();
                     $secToTime = $mixedUtils->sec2Time($time_of_leave_early);
                                        
                     $dataReports[$usrIndex][$associativeIndex][$dateIndex]["pulang_awal"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                  }
                  
                  // --- Check keterlambatan dan pulang awal dengan kondisi ada IN dan ada OUT
                  if (($countIN != 0) && ($countOUT != 0)) {
                     
                     // Terlambat
                     if ($absence->isComeLate(date('Y-m-d H:i:s',$minTime))) {
                        $time_of_late = $time_of_late + $absence->calculateTotalHoursOfLate('COMPLETE',date('Y-m-d H:i:s',$minTime));
                        
                        $mixedUtils = new MixedUtils();
                        $secToTime = $mixedUtils->sec2Time($time_of_late);
                        
                        $dataReports[$usrIndex][$associativeIndex][$dateIndex]["terlambat"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                     }
                     
                     // Pulang awal
                     if ($absence->isLeaveEarly(date('Y-m-d H:i:s',$maxTime))) {
                        $time_of_leave_early = $time_of_leave_early + $absence->calculateTotalHoursOfLeaveEarly('COMPLETE',date('Y-m-d H:i:s',$maxTime));
                     
                        $mixedUtils = new MixedUtils();
                        $secToTime = $mixedUtils->sec2Time($time_of_leave_early);
                        
                        $dataReports[$usrIndex][$associativeIndex][$dateIndex]["pulang_awal"] = $secToTime["hours"].':'.$secToTime["minutes"].':'.$secToTime["seconds"];
                     }
                     
                     // Check apakah overtime
                     if ($absence->isOverTime(date('Y-m-d H:i:s',$maxTime))) {

                        $timediff_overtime = $maxTime - strtotime($absence->getOverTimeBegin());
                        $time_of_overtime = $time_of_overtime+$timediff_overtime;
                        $secToTime = $mixedUtils->sec2Time($time_of_overtime);

                        $dataReports[$usrIndex][$associativeIndex][$dateIndex]["lembur"] = $secToTime["hours"].":".$secToTime["minutes"].":".$secToTime["seconds"];
                     }
                  }
                  
                  // END hitung absen
               }
               
            } else { // START IF UNTUK JIKA TIDAK ADA JADWAL
               
               $go_ahead = true;
            }
            
            $dateIndex++;
            
            $notpresent = 0;
            $time_of_late = 0;
            $time_of_leave_early = 0;
            $time_of_overtime = 0;
         }
         
         $usrIndex++;
      }
      
      $this->set('dataReports',$dataReports);
       
   }
    
   private function __listDateFromDateRange($startdate,$enddate) {
      $listOfDate = array();

      array_push($listOfDate,$startdate);

      $c = 1;
      while (true) {
         $date = strtotime(date("Y-m-d",strtotime($startdate))."+".$c." day");
         $str_date = date("Y-m-d",$date);

         if ($str_date !== $enddate) {
            array_push($listOfDate,$str_date);
         } else {
            array_push($listOfDate,$enddate);
            break;
         }

         $c++;
         
      }
      
      return $listOfDate;
   }
      
   private function __getDayOrder($date, $start_date, $cycle) {
      $day_init = strtotime(date("Y-m-d",strtotime($date))."+1 day");
      $day_second = $day_init - strtotime($start_date);
      $days_amount_in_second = 86400 * $cycle;
      $day = $day_second % $days_amount_in_second;

      $day_order = $day / 86400;

      if ($day_order == 0) {
         $day_order = $cycle;
      }

      return $day_order;
   }
   
   private function __addDateToEachTime($timeList = array(), $date = '', $nextDate = '') {
      
      $acuanTime = strtotime('t'.$timeList['JamKerja']['batas_awal_masuk']);

      $timeList['JamKerja']['waktu_masuk'] = $date.' '.$timeList['JamKerja']['waktu_masuk'];
      $timeList['JamKerja']['batas_awal_masuk'] = $date.' '.$timeList['JamKerja']['batas_awal_masuk'];

      if (strtotime('t'.$timeList['JamKerja']['waktu_keluar']) > $acuanTime) {
         $timeList['JamKerja']['waktu_keluar'] = $date.' '.$timeList['JamKerja']['waktu_keluar'];
      } else {
         $timeList['JamKerja']['waktu_keluar'] = $nextDate.' '.$timeList['JamKerja']['waktu_keluar'];
      }

      if (strtotime('t'.$timeList['JamKerja']['batas_akhir_masuk']) > $acuanTime) {
         $timeList['JamKerja']['batas_akhir_masuk'] = $date.' '.$timeList['JamKerja']['batas_akhir_masuk'];
      } else {
         $timeList['JamKerja']['batas_akhir_masuk'] = $nextDate.' '.$timeList['JamKerja']['batas_akhir_masuk'];
      }

      if (strtotime('t'.$timeList['JamKerja']['batas_awal_keluar']) > $acuanTime) {
         $timeList['JamKerja']['batas_awal_keluar'] = $date.' '.$timeList['JamKerja']['batas_awal_keluar'];
      } else {
         $timeList['JamKerja']['batas_awal_keluar'] = $nextDate.' '.$timeList['JamKerja']['batas_awal_keluar'];
      }

      if (strtotime('t'.$timeList['JamKerja']['batas_akhir_keluar']) > $acuanTime) {
         $timeList['JamKerja']['batas_akhir_keluar'] = $date.' '.$timeList['JamKerja']['batas_akhir_keluar'];
      } else {
         $timeList['JamKerja']['batas_akhir_keluar'] = $nextDate.' '.$timeList['JamKerja']['batas_akhir_keluar'];
      }

      if (strtotime('t'.$timeList['JamKerja']['waktu_toleransi_telat']) > $acuanTime) {
         $timeList['JamKerja']['waktu_toleransi_telat'] = $date.' '.$timeList['JamKerja']['waktu_toleransi_telat'];
      } else {
         $timeList['JamKerja']['waktu_toleransi_telat'] = $nextDate.' '.$timeList['JamKerja']['waktu_toleransi_telat'];
      }

      if (strtotime('t'.$timeList['JamKerja']['waktu_toleransi_keluar_awal']) > $acuanTime) {
         $timeList['JamKerja']['waktu_toleransi_keluar_awal'] = $date.' '.$timeList['JamKerja']['waktu_toleransi_keluar_awal'];
      } else {
         $timeList['JamKerja']['waktu_toleransi_keluar_awal'] = $nextDate.' '.$timeList['JamKerja']['waktu_toleransi_keluar_awal'];
      }

      if (strtotime('t'.$timeList['JamKerja']['waktu_awal_lembur']) > $acuanTime) {
         $timeList['JamKerja']['waktu_awal_lembur'] = $date.' '.$timeList['JamKerja']['waktu_awal_lembur'];
      } else {
         $timeList['JamKerja']['waktu_awal_lembur'] = $nextDate.' '.$timeList['JamKerja']['waktu_awal_lembur'];
      }
      
      return $timeList;
   }
}
